package daybook.model;

import daybook.model.transaction.ImmutableTransactionEntry;
import daybook.model.transaction.ImmutableItem;
import daybook.model.transaction.ImmutableTransaction;
import daybook.model.transaction.Transaction;
import daybook.util.tree.ImmutableTree;
import daybook.util.tree.Tree;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static java.util.Arrays.asList;

public final class Example {
    private Example() {}

    public static final Commodity CNY = Commodity.CNY;
    public static final Commodity DABAO = ImmutableCommodity.builder()
            .name("DABAO").currency(false).fractionDigitCount(2)
            .description("大宝货币基金").build();
    public static final Commodity WENDING = ImmutableCommodity.builder()
            .name("WENDING").currency(false).fractionDigitCount(2)
            .description("稳定债券基金").build();
    public static final Map<String, Commodity> COMMODITIES;
    static {
        final Map<String, Commodity> commodities = new HashMap<>(3);
        commodities.put(CNY.getName(), CNY);
        commodities.put(DABAO.getName(), DABAO);
        commodities.put(WENDING.getName(), WENDING);
        COMMODITIES = Collections.unmodifiableMap(commodities);
    }

    // Top Level Account
    public static final Account 资产账户 = ImmutableAccount.builder()
            .code("A").name("资产").type(Account.Type.ASSET).build();
    public static final Account 权益账户 = ImmutableAccount.builder()
            .code("C").name("所有者权益").type(Account.Type.EQUITY).build();
    public static final Account 负债账户 = ImmutableAccount.builder()
            .code("L").name("负债").type(Account.Type.LIABILITY).build();
    public static final Account 收入账户 = ImmutableAccount.builder()
            .code("R").name("收入").type(Account.Type.REVENUE).build();
    public static final Account 费用账户 = ImmutableAccount.builder()
            .code("E").name("费用").type(Account.Type.EXPENSE).build();

    // 资产
    public static final Account 现金账户 = ImmutableAccount.builder()
            .code("A01").name("现金").type(Account.Type.ASSET)
            .addAttributes("Cash")
            .parentCode(资产账户.getCode()).build();
    public static final Account 工行借记卡账户 = ImmutableAccount.builder()
            .code("A02").name("工行借记卡").type(Account.Type.ASSET)
            .addAttributes("Cash")
            .addAliases("工资卡")
            .parentCode(资产账户.getCode()).build();
    public static final Account 农行借记卡账户 = ImmutableAccount.builder()
            .code("A03").name("农行借记卡").type(Account.Type.ASSET)
            .addAttributes("Cash")
            .parentCode(资产账户.getCode()).build();
    public static final Account 应收账款账户 = ImmutableAccount.builder()
            .code("A04").name("应收账款").type(Account.Type.ASSET)
            .parentCode(资产账户.getCode()).build();
    public static final Account 大宝货币基金账户 = ImmutableAccount.builder()
            .code("A05").name("大宝货币基金").type(Account.Type.ASSET)
            .addAttributes("Cash").addAttributes("Security")
            .parentCode(资产账户.getCode()).commodity(DABAO).build();
    public static final Account 稳定债券基金账户 = ImmutableAccount.builder()
            .code("A06").name("稳定债券基金").type(Account.Type.ASSET)
            .addAttributes("Security")
            .parentCode(资产账户.getCode()).commodity(WENDING).build();

    // 权益
    public static final Account 期初余额账户 = ImmutableAccount.builder()
            .code("C01").name("期初余额").type(Account.Type.EQUITY)
            .parentCode(权益账户.getCode()).build();

    // 负债
    public static final Account 工行贷记卡账户 = ImmutableAccount.builder()
            .code("L01").name("工行贷记卡").type(Account.Type.LIABILITY)
            .parentCode(负债账户.getCode()).build();
    public static final Account 应付账款账户 = ImmutableAccount.builder()
            .code("L02").name("应付账款").type(Account.Type.LIABILITY)
            .parentCode(负债账户.getCode()).build();

    // 收入
    public static final Account 工资账户 = ImmutableAccount.builder()
            .code("R01").name("工资").type(Account.Type.REVENUE)
            .parentCode(收入账户.getCode()).build();
    public static final Account 利息账户 = ImmutableAccount.builder()
            .code("R02").name("利息").type(Account.Type.REVENUE)
            .parentCode(收入账户.getCode()).build();
    public static final Account 红利账户 = ImmutableAccount.builder()
            .code("R03").name("红利").type(Account.Type.REVENUE)
            .parentCode(收入账户.getCode()).build();

    // 费用
    public static final Account 餐饮费账户 = ImmutableAccount.builder()
            .code("E01").name("餐饮费").type(Account.Type.EXPENSE)
            .parentCode(费用账户.getCode()).build();
    public static final Account 交通费账户 = ImmutableAccount.builder()
            .code("E02").name("交通费").type(Account.Type.EXPENSE)
            .parentCode(费用账户.getCode()).build();
    public static final Account 水电费账户 = ImmutableAccount.builder()
            .code("E03").name("水电费").type(Account.Type.EXPENSE)
            .parentCode(费用账户.getCode()).build();
    public static final Account 银行卡服务费账户 = ImmutableAccount.builder()
            .code("E04").name("银行卡服务费").type(Account.Type.EXPENSE)
            .parentCode(费用账户.getCode()).build();
    public static final Account 日常杂费账户 = ImmutableAccount.builder()
            .code("E05").name("日常杂费").type(Account.Type.EXPENSE)
            .parentCode(费用账户.getCode()).build();

    public static final ChartOfAccounts CHART_OF_ACCOUNTS = ChartOfAccounts.of(
            ImmutableTree.of(Account.ROOT,
                    asList(ImmutableTree.of(资产账户,
                            asList(Tree.of(现金账户),
                                    Tree.of(工行借记卡账户),
                                    Tree.of(农行借记卡账户),
                                    Tree.of(应收账款账户),
                                    Tree.of(大宝货币基金账户),
                                    Tree.of(稳定债券基金账户))),
                            ImmutableTree.of(权益账户,
                                    Collections.singletonList(Tree.of(期初余额账户))),
                            ImmutableTree.of(负债账户,
                                    asList(Tree.of(工行贷记卡账户),
                                            Tree.of(应付账款账户))),
                            ImmutableTree.of(收入账户,
                                    asList(Tree.of(工资账户),
                                            Tree.of(利息账户),
                                            Tree.of(红利账户))),
                            ImmutableTree.of(费用账户,
                                    asList(Tree.of(餐饮费账户),
                                            Tree.of(交通费账户),
                                            Tree.of(水电费账户),
                                            Tree.of(银行卡服务费账户),
                                            Tree.of(日常杂费账户))))),
            "|");

    // Book
    public static final Book BOOK = ImmutableBook.builder()
            .accountNameSeparator("|")
            .defaultCurrency(CNY)
            .commodities(COMMODITIES)
            .chartOfAccounts(CHART_OF_ACCOUNTS)
            .build();

    public static final List<Transaction> transactions = asList(
            ImmutableTransaction.builder()
                    .date(LocalDate.of(2016, 5, 31))
                    .order(1)
                    .description("发工资")
                    .addEntries(ImmutableTransactionEntry.builder()
                            .account(工资账户)
                            .amount(new BigDecimal("-5000.00")).build())
                    .addEntries(ImmutableTransactionEntry.builder()
                            .account(工行借记卡账户)
                            .amount(new BigDecimal("5000.00")).build())
                    .build(),
            ImmutableTransaction.builder()
                    .date(LocalDate.of(2016, 6, 1))
                    .order(2)
                    .description("交水费")
                    .addEntries(ImmutableTransactionEntry.builder()
                            .account(水电费账户)
                            .amount(new BigDecimal("25.00"))
                            .build())
                    .addEntries(ImmutableTransactionEntry.builder()
                            .account(现金账户)
                            .amount(new BigDecimal("-25.00"))
                            .build())
                    .build(),
            ImmutableTransaction.builder()
                    .date(LocalDate.of(2016, 6, 1))
                    .order(3)
                    .description("买菜")
                    .addEntries(ImmutableTransactionEntry.builder()
                            .account(餐饮费账户)
                            .amount(new BigDecimal("60.00"))
                            .build())
                    .addEntries(ImmutableTransactionEntry.builder()
                            .account(现金账户)
                            .amount(new BigDecimal("-60.00"))
                            .build())
                    .build(),
            ImmutableTransaction.builder()
                    .date(LocalDate.of(2016, 6, 2))
                    .order(4)
                    .description("回老家")
                    .addEntries(ImmutableTransactionEntry.builder()
                            .account(工行借记卡账户)
                            .amount(new BigDecimal("-100.00"))
                            .build())
                    .addEntries(ImmutableTransactionEntry.builder()
                            .account(交通费账户)
                            .amount(new BigDecimal("95.00"))
                            .addTags("火车")
                            .build())
                    .addEntries(ImmutableTransactionEntry.builder()
                            .account(交通费账户)
                            .amount(new  BigDecimal("5.00"))
                            .addTags("地铁")
                            .build())
                    .build(),
            ImmutableTransaction.builder()
                    .date(LocalDate.of(2016, 6, 3))
                    .order(5)
                    .description("还信用卡")
                    .addEntries(ImmutableTransactionEntry.builder()
                            .account(工行贷记卡账户)
                            .amount(new BigDecimal("340.00"))
                            .build())
                    .addEntries(ImmutableTransactionEntry.builder()
                            .account(工行借记卡账户)
                            .amount(new BigDecimal("-340.00"))
                            .build())
                    .build(),
            ImmutableTransaction.builder()
                    .date(LocalDate.of(2016, 6, 4))
                    .order(6)
                    .description("银行卡利息和年费")
                    .addEntries(ImmutableTransactionEntry.builder()
                            .account(工行借记卡账户)
                            .description("银行卡年费")
                            .amount(new BigDecimal("-10.00"))
                            .build())
                    .addEntries(ImmutableTransactionEntry.builder()
                            .account(银行卡服务费账户)
                            .description("银行卡年费")
                            .amount(new BigDecimal("+10.00"))
                            .build())
                    .addEntries(ImmutableTransactionEntry.builder()
                            .account(工行借记卡账户)
                            .description("活期利息")
                            .amount(new BigDecimal("+10.00"))
                            .build())
                    .addEntries(ImmutableTransactionEntry.builder()
                            .account(利息账户)
                            .description("活期利息")
                            .amount(new BigDecimal("-10.00"))
                            .build())
                    .build(),
            ImmutableTransaction.builder()
                    .date(LocalDate.of(2016, 6, 6))
                    .order(7)
                    .description("买入大宝货币基金")
                    .addEntries(ImmutableTransactionEntry.builder()
                            .account(大宝货币基金账户)
                            .amount(new BigDecimal("1000.00"))
                            .addItems(ImmutableItem.builder()
                                    .cost(new BigDecimal("1.00"))
                                    .count(new BigDecimal("1000.00"))
                                    .build())
                            .build())
                    .addEntries(ImmutableTransactionEntry.builder()
                            .account(工行借记卡账户)
                            .amount(new BigDecimal("-1000.00"))
                            .build())
                    .build(),
            ImmutableTransaction.builder()
                    .date(LocalDate.of(2016, 6, 6))
                    .order(8)
                    .description("买入稳定债券基金")
                    .addEntries(ImmutableTransactionEntry.builder()
                            .account(稳定债券基金账户)
                            .amount(new BigDecimal("500.00"))
                            .addItems(ImmutableItem.builder()
                                    .cost(new BigDecimal("2.00"))
                                    .count(new BigDecimal("250.00"))
                                    .build())
                            .build())
                    .addEntries(ImmutableTransactionEntry.builder()
                            .account(工行借记卡账户)
                            .amount(new BigDecimal("-500.00"))
                            .build())
                    .build(),
            ImmutableTransaction.builder()
                    .date(LocalDate.of(2016, 6, 7))
                    .order(9)
                    .description("大宝货币基金收入")
                    .addEntries(ImmutableTransactionEntry.builder()
                            .account(大宝货币基金账户)
                            .amount(new BigDecimal("0.15"))
                            .addItems(ImmutableItem.builder()
                                    .cost(new BigDecimal("1.00"))
                                    .count(new BigDecimal("0.15"))
                                    .build())
                            .build())
                    .addEntries(ImmutableTransactionEntry.builder()
                            .account(红利账户)
                            .amount(new BigDecimal("-0.15"))
                            .build())
                    .build(),
            ImmutableTransaction.builder()
                    .date(LocalDate.of(2016, 6, 8))
                    .order(10)
                    .description("大宝货币基金收入")
                    .addEntries(ImmutableTransactionEntry.builder()
                            .account(大宝货币基金账户)
                            .amount(new BigDecimal("0.10"))
                            .addItems(ImmutableItem.builder()
                                    .cost(new BigDecimal("1.00"))
                                    .count(new BigDecimal("0.10"))
                                    .build())
                            .build())
                    .addEntries(ImmutableTransactionEntry.builder()
                            .account(红利账户)
                            .amount(new BigDecimal("-0.10"))
                            .build())
                    .build(),
            ImmutableTransaction.builder()
                    .date(LocalDate.of(2016, 6, 9))
                    .order(11)
                    .description("大宝货币基金收入")
                    .addEntries(ImmutableTransactionEntry.builder()
                            .account(大宝货币基金账户)
                            .amount(new BigDecimal("0.16"))
                            .addItems(ImmutableItem.builder()
                                    .cost(new BigDecimal("1.00"))
                                    .count(new BigDecimal("0.16"))
                                    .build())
                            .build())
                    .addEntries(ImmutableTransactionEntry.builder()
                            .account(红利账户)
                            .amount(new BigDecimal("-0.16"))
                            .build())
                    .build(),
            ImmutableTransaction.builder()
                    .date(LocalDate.of(2016, 6, 9))
                    .order(12)
                    .description("稳定债券基金分红")
                    .addEntries(ImmutableTransactionEntry.builder()
                            .account(稳定债券基金账户)
                            .amount(new BigDecimal("-25.00"))
                            .description("分红前每份价格2.05, 分红后价格每份价格1.90")
                            .build())
                    .addEntries(ImmutableTransactionEntry.builder()
                            .account(红利账户)
                            .amount(new BigDecimal("-12.50"))
                            .build())
                    .addEntries(ImmutableTransactionEntry.builder()
                            .account(工行借记卡账户)
                            .amount(new BigDecimal("37.50"))
                            .build())
                    .build(),
            ImmutableTransaction.builder()
                    .date(LocalDate.of(2016, 6, 10))
                    .order(13)
                    .description("卖出稳定债券基金")
                    .addEntries(ImmutableTransactionEntry.builder()
                            .account(稳定债券基金账户)
                            .amount(new BigDecimal("-475.00"))
                            .addItems(ImmutableItem.builder()
                                    .cost(new BigDecimal("1.90"))
                                    .count(new BigDecimal("250.00"))
                                    .build())
                            .description("卖出价格每份1.89")
                            .build())
                    .addEntries(ImmutableTransactionEntry.builder()
                            .account(红利账户)
                            .amount(new BigDecimal("2.50"))
                            .build())
                    .addEntries(ImmutableTransactionEntry.builder()
                            .account(工行借记卡账户)
                            .amount(new BigDecimal("472.50"))
                            .build())
                    .build(),
            ImmutableTransaction.builder()
                    .date(LocalDate.of(2016, 6, 10))
                    .order(14)
                    .description("大宝货币基金收入")
                    .addEntries(ImmutableTransactionEntry.builder()
                            .account(大宝货币基金账户)
                            .amount(new BigDecimal("0.11"))
                            .addItems(ImmutableItem.builder()
                                    .cost(new BigDecimal("1.00"))
                                    .count(new BigDecimal("0.11"))
                                    .build())
                            .build())
                    .addEntries(ImmutableTransactionEntry.builder()
                            .account(红利账户)
                            .amount(new BigDecimal("-0.11"))
                            .build())
                    .build()
    );
}
